using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Hosting;
using Toast.Core;
using Toast.Core.Interfaces;
using Toast.Extensions;

namespace Toast.ContentTypes
{
    [Serializable]
    public sealed class EmbededJavaScriptContent : JavaScriptContentBase
    {
        public EmbededJavaScriptContent()
        {
        }

        EmbededJavaScriptContent(string content,  InjectAt injectAt, ICompressionStrategy javaScriptCompression)
        {
            Content = content;
            FileName = GenerateFileName();
            InjectAt = injectAt;
            Compression = javaScriptCompression;
        }

        public override bool TryConstructFrom(string from, out IContent result)
        {
            if (!Regex.IsMatch(from, @"[\s\;]+"))
            {
                result = null;
                return false;
            }

            result = new EmbededJavaScriptContent(from, InjectAt.Default, Core.ToastCore.Compression().For<IJavaScriptContent>());
            return true;
        }

        public string Content { get; set; }

        public override IInjectionFormatter GetFormatter(string packageKey)
        {
           return new EmbededInjectionFormatter(packageKey); 
        }

        public static EmbededJavaScriptContent ContentIs(string content)
        {
            return ContentIs(content, InjectAt.Inline, Core.ToastCore.Compression().For<IJavaScriptContent>());
        }

        public static EmbededJavaScriptContent ContentIs(string content,  InjectAt injectAt)
        {
            return ContentIs(content, injectAt, Core.ToastCore.Compression().For<IJavaScriptContent>());
        }

        public static EmbededJavaScriptContent ContentIs(string content, InjectAt injectAt, ICompressionStrategy javaScriptCompression)
        {
            return new EmbededJavaScriptContent(content, injectAt, javaScriptCompression);
        }

        public static EmbededJavaScriptContent ContentIs(string content, ICompressionStrategy javaScriptCompression)
        {
            return new EmbededJavaScriptContent(content, InjectAt.Default, javaScriptCompression);
        }

        public static EmbededJavaScriptContent FromFile(string filePath)
        {
            return FromFile(filePath, InjectAt.Default);
        }

        public static EmbededJavaScriptContent FromFile(string filePath, InjectAt injectAt)
        {
            return FromFile(filePath, injectAt, Core.ToastCore.Compression().For<IJavaScriptContent>());
        }

        public static EmbededJavaScriptContent FromFile(string filePath, IJavaScriptCompressionStrategy javaScriptCompression)
        {
            return FromFile(filePath, InjectAt.Default, javaScriptCompression);
        }

        public static EmbededJavaScriptContent FromFile(string filePath, InjectAt injectAt, ICompressionStrategy javaScriptCompression)
        {
            var fullPath = HostingEnvironment.MapPath(filePath);

            if (fullPath == null || !File.Exists(fullPath))
                return null;

            var content = File.ReadAllText(fullPath);

            return ContentIs(content,  injectAt, javaScriptCompression);
        }
    }

    public class EmbededInjectionFormatter : InjectionFormatter
    {
        readonly string _packageKey;

        public EmbededInjectionFormatter(string packageKey)
            : base("<script type='text/javascript'>{0}</script>")
        {
            _packageKey = packageKey;
        }

        public override string Format(IContent javaScriptContent, bool seperate)
        {
            var typedScript = javaScriptContent as EmbededJavaScriptContent;

            if (typedScript == null)
                return null;

            return seperate
                       ? InjectionFormatString.FormatWith(typedScript.Content)
                       : typedScript.Content;
        }

        public override string Format(IEnumerable<IContent> scripts, bool seperate)
        {

            return scripts == null ? null : InjectionFormatString.FormatWith(scripts.Select(x => Format(x, seperate)).Join("\r\n"));
        }
    }
}